﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.

using System.Threading.Tasks;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
    Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines.CSharpImplementStandardExceptionConstructorsAnalyzer,
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.ImplementStandardExceptionConstructorsFixer>;
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
    Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines.BasicImplementStandardExceptionConstructorsAnalyzer,
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.ImplementStandardExceptionConstructorsFixer>;

namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.UnitTests
{
    public class ImplementStandardExceptionConstructorsFixerTests
    {
        #region CSharpUnitTests
        //Note: In the test cases you won't see a missing all 3 constructors scenario, because that will never occur since default constructor is always generated by system in that case

        [Fact]
        public async Task TestCSFixMissingTwoCtors_Case1Async()
        {
            var code = @"
using System;
public class [|[|SomeException|]|] : Exception
{
    public SomeException()
    {
    }
}
";
            var fix = @"
using System;
public class SomeException : Exception
{
    public SomeException()
    {
    }

    public SomeException(string message) : base(message)
    {
    }

    public SomeException(string message, Exception innerException) : base(message, innerException)
    {
    }
}
";
            await new VerifyCS.Test
            {
                TestState = { Sources = { code } },
                FixedState = { Sources = { fix } },
                NumberOfFixAllIterations = 2,
            }.RunAsync();
        }

        [Fact]
        public async Task TestCSFixMissingTwoCtors_Case2Async()
        {
            var code = @"
using System;
public class [|[|SomeException|]|] : Exception
{
    public SomeException(string message)
    {
    }
}
";
            var fix = @"
using System;
public class SomeException : Exception
{
    public SomeException(string message)
    {
    }

    public SomeException()
    {
    }

    public SomeException(string message, Exception innerException) : base(message, innerException)
    {
    }
}
";
            await new VerifyCS.Test
            {
                TestState = { Sources = { code } },
                FixedState = { Sources = { fix } },
                NumberOfFixAllIterations = 2,
            }.RunAsync();
        }

        [Fact]
        public async Task TestCSFixMissingTwoCtors_Case3Async()
        {
            var code = @"
using System;
public class [|[|SomeException|]|] : Exception
{
    public SomeException(string message, Exception innerException)
    {
    }
}
";
            var fix = @"
using System;
public class SomeException : Exception
{
    public SomeException(string message, Exception innerException)
    {
    }

    public SomeException()
    {
    }

    public SomeException(string message) : base(message)
    {
    }
}
";
            await new VerifyCS.Test
            {
                TestState = { Sources = { code } },
                FixedState = { Sources = { fix } },
                NumberOfFixAllIterations = 2,
            }.RunAsync();
        }

        [Fact]
        public async Task TestCSFixMissingOneCtor_Case1Async()
        {
            var code = @"
using System;
public class [|SomeException|] : Exception
{
    public SomeException(string message): base(message)
    {
    }

    public SomeException(string message, Exception innerException) : base(message, innerException)
    {
    }

}
";
            var fix = @"
using System;
public class SomeException : Exception
{
    public SomeException(string message): base(message)
    {
    }

    public SomeException(string message, Exception innerException) : base(message, innerException)
    {
    }

    public SomeException()
    {
    }
}
";
            await VerifyCS.VerifyCodeFixAsync(code, fix);
        }

        [Fact]
        public async Task TestCSFixMissingOneCtor_Case2Async()
        {
            var code = @"
using System;
public class [|SomeException|] : Exception
{
    public SomeException()
    {
    }

    public SomeException(string message)
    {
    }

}
";
            var fix = @"
using System;
public class SomeException : Exception
{
    public SomeException()
    {
    }

    public SomeException(string message)
    {
    }

    public SomeException(string message, Exception innerException) : base(message, innerException)
    {
    }
}
";
            await VerifyCS.VerifyCodeFixAsync(code, fix);
        }

        [Fact]
        public async Task TestCSFixMissingOneCtor_Case3Async()
        {
            var code = @"
using System;
public class [|SomeException|] : Exception
{
    public SomeException()
    {
    }

    public SomeException(string message, Exception innerException)
    {
    }

}
";
            var fix = @"
using System;
public class SomeException : Exception
{
    public SomeException()
    {
    }

    public SomeException(string message, Exception innerException)
    {
    }

    public SomeException(string message) : base(message)
    {
    }
}
";
            await VerifyCS.VerifyCodeFixAsync(code, fix);
        }

        #endregion

        #region BasicUnitTests
        //Note: In the test cases you won't see a missing all 3 constructors scenario, because that will never occur since default constructor is always generated by system in that case

        [Fact]
        public async Task TestVBFixMissingTwoCtors_Case1Async()
        {
            var code = @"
Imports System
Public Class [|[|SomeException|]|] : Inherits Exception
    Public Sub New()
    End Sub
End Class
";
            var fix = @"
Imports System
Public Class SomeException : Inherits Exception
    Public Sub New()
    End Sub

    Public Sub New(message As String)
        MyBase.New(message)
    End Sub

    Public Sub New(message As String, innerException As Exception)
        MyBase.New(message, innerException)
    End Sub
End Class
";
            await new VerifyVB.Test
            {
                TestState = { Sources = { code } },
                FixedState = { Sources = { fix } },
                NumberOfFixAllIterations = 2,
            }.RunAsync();
        }

        [Fact]
        public async Task TestVBFixMissingTwoCtors_Case2Async()
        {
            var code = @"
Imports System
Public Class [|[|SomeException|]|] : Inherits Exception
    Public Sub New(message As String)
    End Sub
End Class
";
            var fix = @"
Imports System
Public Class SomeException : Inherits Exception
    Public Sub New(message As String)
    End Sub

    Public Sub New()
    End Sub

    Public Sub New(message As String, innerException As Exception)
        MyBase.New(message, innerException)
    End Sub
End Class
";
            await new VerifyVB.Test
            {
                TestState = { Sources = { code } },
                FixedState = { Sources = { fix } },
                NumberOfFixAllIterations = 2,
            }.RunAsync();
        }

        [Fact]
        public async Task TestVBFixMissingTwoCtors_Case3Async()
        {
            var code = @"
Imports System
Public Class [|[|SomeException|]|] : Inherits Exception
    Public Sub New(message As String, innerException As Exception)
    End Sub
End Class
";
            var fix = @"
Imports System
Public Class SomeException : Inherits Exception
    Public Sub New(message As String, innerException As Exception)
    End Sub

    Public Sub New()
    End Sub

    Public Sub New(message As String)
        MyBase.New(message)
    End Sub
End Class
";
            await new VerifyVB.Test
            {
                TestState = { Sources = { code } },
                FixedState = { Sources = { fix } },
                NumberOfFixAllIterations = 2,
            }.RunAsync();
        }

        [Fact]
        public async Task TestVBFixMissingOneCtor_Case1Async()
        {
            var code = @"
Imports System
Public Class [|SomeException|] : Inherits Exception
    Public Sub New()
    End Sub

    Public Sub New(message As String)
    End Sub
End Class
";
            var fix = @"
Imports System
Public Class SomeException : Inherits Exception
    Public Sub New()
    End Sub

    Public Sub New(message As String)
    End Sub

    Public Sub New(message As String, innerException As Exception)
        MyBase.New(message, innerException)
    End Sub
End Class
";
            await VerifyVB.VerifyCodeFixAsync(code, fix);
        }

        [Fact]
        public async Task TestVBFixMissingOneCtor_Case2Async()
        {
            var code = @"
Imports System
Public Class [|SomeException|] : Inherits Exception
    Public Sub New()
    End Sub

    Public Sub New(message As String, innerException As Exception)
    End Sub
End Class
";
            var fix = @"
Imports System
Public Class SomeException : Inherits Exception
    Public Sub New()
    End Sub

    Public Sub New(message As String, innerException As Exception)
    End Sub

    Public Sub New(message As String)
        MyBase.New(message)
    End Sub
End Class
";
            await VerifyVB.VerifyCodeFixAsync(code, fix);
        }

        [Fact]
        public async Task TestVBFixMissingOneCtor_Case3Async()
        {
            var code = @"
Imports System
Public Class [|SomeException|] : Inherits Exception
    Public Sub New(message As String)
    End Sub

    Public Sub New(message As String, innerException As Exception)
    End Sub
End Class
";
            var fix = @"
Imports System
Public Class SomeException : Inherits Exception
    Public Sub New(message As String)
    End Sub

    Public Sub New(message As String, innerException As Exception)
    End Sub

    Public Sub New()
    End Sub
End Class
";
            await VerifyVB.VerifyCodeFixAsync(code, fix);
        }
        #endregion
    }
}